﻿// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动！任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任！

using Admin.NET.Core.Service;
using EasyTest.Application.Const;
using EasyTest.Application.Service.QuestionBank.Dto;
using Microsoft.AspNetCore.Http;
namespace EasyTest.Application.Service.QuestionBank;

/// <summary>
/// 题目分类服务
/// </summary>
[ApiDescriptionSettings(ApplicationConst.GroupName, Order = 100)]
public class EtQuestionCateService : IDynamicApiController, ITransient
{
    private readonly SqlSugarRepository<EtQuestionCate> _etQuestionCateRep;
    private readonly SqlSugarRepository<EtQuestionBank> _etQuestionBankRep;
    private readonly SqlSugarRepository<EtQuestion> _questionRep;
    public EtQuestionCateService(SqlSugarRepository<EtQuestionCate> etQuestionCateRep, 
        SqlSugarRepository<EtQuestionBank> etQuestionBankRep
        //SqlSugarRepository<EtQuestion> questionRep
        )
    {
        _etQuestionCateRep = etQuestionCateRep;
        _etQuestionBankRep = etQuestionBankRep;
        //_questionRep = questionRep;
    }

    /// <summary>
    /// 分页查询题目分类
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Page")]
    [DisplayName("分页查询题目分类")]
    public async Task<SqlSugarPagedList<EtQuestionCateOutput>> Page(PageEtQuestionCateInput input)
    {
        input.SearchKey = input.SearchKey?.Trim();
        var query = _etQuestionCateRep.AsQueryable()
            .WhereIF(!string.IsNullOrEmpty(input.SearchKey), u =>
                u.Name.Contains(input.SearchKey)
            )
            .WhereIF(!string.IsNullOrWhiteSpace(input.Name), u => u.Name.Contains(input.Name.Trim()))
            .WhereIF(input.ParentId > 0, u => u.ParentId == input.ParentId)
            .WhereIF(input.OrderNo > 0, u => u.OrderNo == input.OrderNo)
            //处理外键和TreeSelector相关字段的连接
            .LeftJoin<EtQuestionCate>((u, parentid) => u.ParentId == parentid.ParentId)
            .Select((u, parentid) => new EtQuestionCateOutput
            {
                Id = u.Id,
                Name = u.Name,
                Description = u.Description,
                Status = (int)u.Status,
                ParentId = u.ParentId,
                ParentIdName = parentid.Name,
                OrderNo = u.OrderNo,
                TenantId = u.TenantId,
                CreateOrgId = u.CreateOrgId,
                CreateOrgName = u.CreateOrgName,
                CreateTime = u.CreateTime,
                UpdateTime = u.UpdateTime,
                CreateUserId = u.CreateUserId,
                CreateUserName = u.CreateUserName,
                UpdateUserId = u.UpdateUserId,
                UpdateUserName = u.UpdateUserName,
                IsDelete = u.IsDelete,
            });
        return await query.OrderBuilder(input).ToPagedListAsync(input.Page, input.PageSize);
    }

    /// <summary>
    /// 增加题目分类
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Add")]
    [DisplayName("增加题目分类")]
    public async Task<long> Add(AddEtQuestionCateInput input)
    {
        // 1. 检查题库是否存在
        var questionBank = await _etQuestionBankRep.GetFirstAsync(u => u.Id == input.QuestionBankId) 
            ?? throw Oops.Oh("所选题库不存在");

        // 2. 检查同级分类名称是否重复
        var exists = await _etQuestionCateRep.IsAnyAsync(u => 
            u.ParentId == input.ParentId && 
            u.QuestionBankId == input.QuestionBankId && 
            u.Name == input.Name);
        if (exists)
            throw Oops.Oh("同级分类下已存在相同名称");

        var entity = input.Adapt<EtQuestionCate>();
        await _etQuestionCateRep.InsertAsync(entity);
        return entity.Id;
    }

    /// <summary>
    /// 删除题目分类
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Delete")]
    [DisplayName("删除题目分类")]
    public async Task Delete(DeleteEtQuestionCateInput input)
    {
        var entity = await _etQuestionCateRep.GetFirstAsync(u => u.Id == input.Id) 
            ?? throw Oops.Oh(ErrorCodeEnum.D1002);

        //// 2. 检查是否有关联的题目
        //var hasQuestions = await _questionRep.IsAnyAsync(u => u.QuestionCateId == input.Id);
        //if (hasQuestions)
        //    throw Oops.Oh("该分类下存在题目，请先移动或删除相关题目");

        // 获取所有子分类ID
        var childIds = await GetAllChildIds(input.Id);
        if(childIds.Any())
        {
            // 删除所有子分类
            await _etQuestionCateRep.DeleteAsync(u => childIds.Contains(u.Id));
        }

        // 删除当前分类
        await _etQuestionCateRep.DeleteAsync(entity);
    }

    /// <summary>
    /// 更新题目分类
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Update")]
    [DisplayName("更新题目分类")]
    public async Task Update(UpdateEtQuestionCateInput input)
    {
        // 1. 检查题库是否存在
        var questionBank = await _etQuestionBankRep.GetFirstAsync(u => u.Id == input.QuestionBankId) 
            ?? throw Oops.Oh("所选题库不存在");

        // 2. 检查是否为循环引用
        if (input.ParentId != 0)
        {
            var parentNode = await _etQuestionCateRep.GetFirstAsync(u => u.Id == input.ParentId)
                ?? throw Oops.Oh("父级分类不存在");
            
            // 检查是否选择了自己或自己的子节点作为父级
            var childIds = await GetAllChildIds(input.Id);
            if (input.Id == input.ParentId || childIds.Contains(input.ParentId))
                throw Oops.Oh("不能选择自己或子分类作为父级");
        }

        // 3. 检查同级分类名称是否重复
        var exists = await _etQuestionCateRep.IsAnyAsync(u => 
            u.Id != input.Id && 
            u.ParentId == input.ParentId && 
            u.QuestionBankId == input.QuestionBankId && 
            u.Name == input.Name);
        if (exists)
            throw Oops.Oh("同级分类下已存在相同名称");

        var entity = input.Adapt<EtQuestionCate>();
        await _etQuestionCateRep.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
    }

    /// <summary>
    /// 获取所有子分类ID
    /// </summary>
    private async Task<List<long>> GetAllChildIds(long parentId)
    {
        var allIds = new List<long>();
        var children = await _etQuestionCateRep.GetListAsync(u => u.ParentId == parentId);
        
        foreach (var child in children)
        {
            allIds.Add(child.Id);
            allIds.AddRange(await GetAllChildIds(child.Id));
        }
        
        return allIds;
    }

    /// <summary>
    /// 获取题目分类
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpGet]
    [ApiDescriptionSettings(Name = "Detail")]
    [DisplayName("获取题目分类")]
    public async Task<EtQuestionCate> Detail([FromQuery] QueryByIdEtQuestionCateInput input)
    {
        return await _etQuestionCateRep.GetFirstAsync(u => u.Id == input.Id);
    }

    /// <summary>
    /// 获取题目分类列表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpGet]
    [ApiDescriptionSettings(Name = "List")]
    [DisplayName("获取题目分类列表")]
    public async Task<List<EtQuestionCateOutput>> List([FromQuery] PageEtQuestionCateInput input)
    {
        var query = _etQuestionCateRep.AsQueryable()
            .WhereIF(!string.IsNullOrEmpty(input.SearchKey), u =>
                u.Name.Contains(input.SearchKey.Trim()) ||
                u.Description.Contains(input.SearchKey.Trim()))
            .WhereIF(!string.IsNullOrEmpty(input.Name), u => u.Name.Contains(input.Name.Trim()))
            .WhereIF(input.ParentId > 0, u => u.ParentId == input.ParentId)
            .WhereIF(input.OrderNo > 0, u => u.OrderNo == input.OrderNo);

        return await query.Select<EtQuestionCateOutput>().ToListAsync();
    }

    /// <summary>
    /// 获取题目分类树形结构
    /// </summary>
    /// <param name="questionBankId">题库ID</param>
    /// <returns></returns>
    [HttpGet("EtQuestionCateTree")]
    [DisplayName("获取题目分类树")]
    public async Task<List<EtQuestionCate>> EtQuestionCateTree([FromQuery] long questionBankId)
    {
        return await _etQuestionCateRep.AsQueryable()
            .Where(u => u.Status == StatusEnum.Enable) // 只获取启用的分类
            .Where(u => u.QuestionBankId == questionBankId).Take(50) // 根据题库ID过滤
            .OrderBy(u => u.OrderNo)  // 按排序号排序
            .ToTreeAsync(u => u.Children, u => u.ParentId, 0); // 使用框架的 ToTreeAsync 方法
    }
}
